package com.cskaoyan.javase.oop3._2inner._1member._1basic;

/**
 * @description: 成员内部类的访问特点
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 在学习成员内部类的访问特点之前,先明确两点:
 *      1.成员内部类和外围类是"好哥们",它们之间的访问不受访问权限限制
 *      2.成员内部类的对象依赖于外围类的对象
 *          a.成员内部类的成员方法中能否直接访问外围类成员?
 *              可以,因为成员内部类的成员方法中也隐含了传参this,this表示当前对象
 *              this在这里指的是成员内部类的对象
 *              既然成员内部类对象都有了,一定存在外围类对象,所以可以直接访问外围类成员
 *
 *          b,外围类成员方法中能否直接访问内部类成员?
 *              不能,外围类对象是不依赖于成员内部类对象的,所以外围类的成员方法中没有隐含内部类对象
 *              如果想要访问内部类成员,需要先创建内部类对象
 *
 *
 * 成员内部类的访问特点
 * - 成员内部类(的成员方法)访问外围类(成员)
 *      由于已经隐含了外围类对象,所以可以直接访问外围类成员
 *      如果外围类成员和自身成员内部类成员同名,咋办?
 *      由于就近原则,如果什么都不写,那么访问的肯定是自身同名的成员,想要作区分,就必须在前面加"东西"
 *      a.如果普通成员同名了,用this指向自身对象,用外围类类名.this指向外围类对象
 *      b.成员内部类没有"static"声明,普通的静态成员不能同名
 *      c.全局常量同名,就用类名点去解决
 *
 * - 外围类访问成员内部类成员
 *      1.成员方法中访问内部类成员
 *          隐含了外围对象自身,但是没有成员内部对象,需要先创建对象
 *          创建对象的方式是: 直接创建
 *          内部类类名 对象名 = new 内部类类名();即可
 *          有了对象后,就用对象名访问即可,如果存在同名,无需区分,只有使用内部类对象名访问的才是内部类成员
 *
 *      2.静态成员方法访问内部类成员
 *          没有隐含任何对象,必须先创建外围类对象,再在外围类对象基础上创建内部类对象
 *          访问成员时,使用谁的对象名访问,成员就是属于谁的,没有同名的概念
 *          语法:
 *              MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();
 *
 * - 外部类访问成员内部类成员
 *          1.外部类不是好兄弟,所以访问权限生效了
 *          2.要想访问内部类成员,首先需要外围类的权限,其次需要内部类的权限,还需要内部类成员的权限
 *          3.怎么创建内部类对象?
 *              先创建外围类对象,再创建成员内部类对象,最后再访问成员
 *              不区分成员方法和静态成员方法,是一个概念,反正都没有外围类对象
 *
 * - 成员内部类访问外部类成员（了解）
 *      创建对象,然后访问,也受访问权限限制
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        //创建内部类对象
        EnclosedClazz ec = new EnclosedClazz();
        //为了体现内部类的从属关系,需要使用外围类类名.内部类类名
        EnclosedClazz.MemberInnerClazz mic = ec.new MemberInnerClazz();

        //上述步骤二合一
        EnclosedClazz.MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();
        System.out.println(mic.a);
        //System.out.println(mic.b);
        mic.testInner();

    }
}

class EnclosedClazz {
    //外围类成员
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    public void testEnclosed() {
        //隐含了外围对象自身,但是没有成员内部对象
        //如果想要访问内部类成员,需要先创建内部类对象
        //怎么创建内部类对象?
        //成员内部类对象的创建依赖于外围类对象,this可以写出来,也可以省略
        //MemberInnerClazz mic = this.new MemberInnerClazz();
        MemberInnerClazz mic = new MemberInnerClazz();
        System.out.println(a);
        System.out.println(mic.a);
    }

    public static void testEnclosedStatic() {
        //先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        //再创建内部类对象
        MemberInnerClazz mic = ec.new MemberInnerClazz();

        //上述步骤,可以链式调用二合一
        MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();

    }


    public class MemberInnerClazz {
        int a;
        private int b = 10;
        static final int D = 30;

        //在成员方法中访问外围类成员
        public void testInner() {
            //该方法隐含了两个对象: 成员内部类自身对象,外围类对象
            //访问外围类成员: 直接访问
            System.out.println(this.a);
            System.out.println(EnclosedClazz.this.b);
            System.out.println(EnclosedClazz.c);
            System.out.println(EnclosedClazz.D);
            System.out.println(MemberInnerClazz.D);
            testEnclosed();
            EnclosedClazz.testEnclosedStatic();
        }
    }
}